/*
 * (C) 2009, Elephant Seven Hamburg Gmbh, 
 * Author: Detlev Wiese
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 
 * use this file except in compliance with the License. You may obtain a copy 
 * of the License at
 *  
 *     http://www.apache.org/licenses/LICENSE-2.0 
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.se and its accompanying notice file is
 * included with the distribution. 
 */ 
package com.e7.streams;

import java.util.Enumeration;
import java.util.Iterator;
import java.util.NoSuchElementException;

/**
 * A stream over a {@link java.util.Collection} or any array object. 
 * In fact any {@link java.util.Iterator}, {@link java.lang.Iterable}
 * or {@link java.util.Enumeration} can be handled by this class. 
 * @param <E> The type of the elements of the collection and 
 * the resulting stream.
 */
public class CollectionStream<E> extends AbstractStream<E> 
	implements Stream<E> 
{
  /**
   * A simple Iterator for arrays.
   * @param <E> the type of the elements of the array.
   */
	public static class ArrayIterator<E> implements Iterator<E> {
		final E[] array; 
		int pos = 0;
		
		public ArrayIterator(E[] array) {
			this.array = array;
		}
		
		public boolean hasNext() {
			return pos < array.length;
		}

		public E next() {
			if (this.hasNext())
				return array[pos++];
			throw new NoSuchElementException();
		}

		public void remove() {
			throw new UnsupportedOperationException();
		}
	}
	
	/**
   * A simple Iterator for enumerations.
   * @param <E> the type of the elements of the array.
   */
  public static class EnumerationIterator<E> implements Iterator<E> {
    final Enumeration<E> enumeration; 
    
    public EnumerationIterator(Enumeration<E> enumeration) {
      this.enumeration = enumeration;
    }
    
    public boolean hasNext() {
      return enumeration.hasMoreElements();
    }

    public E next() {
      return enumeration.nextElement();
    }

    public void remove() {
      throw new UnsupportedOperationException();
    }
  }
  
	private Iterator<E> iterator = null; 
	
	/**
	 * Create an instance!
	 * @param i The java.lang.Iterable to stream
	 */
	public CollectionStream(Iterable<E> i) {
		iterator = i.iterator(); 
	}
	
	/**
	 * Create an instance!
	 * @param i The java.util.Iterator to stream
	 */
	public CollectionStream(Iterator<E> i) {
		iterator = i; 
	}
	
	/**
	 * Create an instance!
	 * @param a An array of elements to stream
	 */
	public CollectionStream(E[] a) {
		iterator = new ArrayIterator<E>(a); //Arrays.asList(a).iterator(); 
	}
	
	/**
	 * Create an instance!
	 * @param e The java.util.Enumeration to stream
	 */
	public CollectionStream(final Enumeration<E> e) {
		iterator = new EnumerationIterator<E>(e);
	}
	
	public boolean hasNext() {
		return iterator.hasNext();
	}

	public E next() {
		return iterator.next();
	}
}
